function Animation(img, animationFramesCrops, fps, wrapAround) {
	this.img = img;
	this.animationFramesCrops = animationFramesCrops;
	this.fps = fps;
	this.frameIdxIncrem = Math.floor(FIXED_UPDATES_IN_A_SECOND/this.fps);
	this.wrapAround = wrapAround;
	
	this.gameStateUpdatesCount = -1;
	
	this.start = function() {
		this.gameStateUpdatesCount = 0;
	};
	
	this.isStarted = function() {
		return this.gameStateUpdatesCount != -1;
	};
	
	this.isOver = function() {
		return this.gameStateUpdatesCount > this.animationFramesCrops.length * this.frameIdxIncrem;
	};
	
	this.onGameStateUpdate = function() {
		if(this.gameStateUpdatesCount>=0) {
			this.gameStateUpdatesCount++;
		}
	};
	
	this.onGraphicsUpdate = function(context, x, y) {
		if(this.gameStateUpdatesCount>=0) {
			var frameCrop = this.animationFramesCrops[this.getFrameIdx()];
			context.drawImage(this.img,
					frameCrop.x, frameCrop.y, frameCrop.width, frameCrop.height, 
					x+frameCrop.dx, y+frameCrop.dy, frameCrop.drawWidth, frameCrop.drawHeight);
		}
	};
	
	this.getFrameIdx = function() {
		if(this.gameStateUpdatesCount>=0) {
			if(this.animationFramesCrops.length == 1) {
				return 0;
			}
			
			var idx = Math.floor(this.gameStateUpdatesCount / this.frameIdxIncrem);
			if(this.wrapAround) {
				return idx % this.animationFramesCrops.length;
			} else {
				return idx < this.animationFramesCrops.length ? idx : this.animationFramesCrops.length-1; 
			}
		};
	};
	
};

function ImgCrop(x, y, dx, dy, width, height, drawWidth, drawHeight) {
	//crop upper-left corner:
	this.x = x;
	this.y = y;
	
	//how much to shift this image from the game elements actual location when drawing it:
	this.dx = dx;
	this.dy = dy;
	
	//crop width (how much to the right from x) and height (how much down from y): 
	this.width = width;
	this.height = height;
		
	//how big should the image be drawn (keep proportional to with/height in order to not distort image):
	this.drawWidth = drawWidth;
	this.drawHeight = drawHeight;
};

function AnimationBundle(standUp, standLeft, standRight, standDown, 
		walkUp, walkLeft, walkRight, walkDown,
		debugLeft, debugRight) {
	
	this.standUp = standUp;	
	this.standLeft = standLeft;
	this.standRight = standRight;
	this.standDown = standDown;
	
	this.walkUp = walkUp;
	this.walkLeft = walkLeft;
	this.walkRight = walkRight;
	this.walkDown = walkDown;
	
	this.debugLeft = debugLeft;
	this.debugRight = debugRight;	
};

function AnimationBundleCreator() {
	
	this.createHumanAnimationBundle = function() {
		var animationHumanUpStand = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_0_0],
				1, true);

		var animationHumanUpWalk = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_0_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationHumanLeftStand = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_1_0],
				1, true);

		var animationHumanLeftWalk = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_1_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_8,
				 ],
				 ANIMATION_WALK_FPS, true);


		var animationHumanDownStand = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_2_0],
				1, true);

		var animationHumanDownWalk = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_2_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationHumanRightStand = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_3_0],
				1, true);

		var animationHumanRightWalk = new Animation(UNIT_HUMAN_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_3_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_8,
				 ],
				 ANIMATION_WALK_FPS, true);
		
		var animationBlueArrowLeft = new Animation(ARROW_BLUE_LEFT_IMG, 
				[UNIT_ARROW_SPRITE_SHEET_CROP],
				1, true);

		var animationBlueArrowRight = new Animation(ARROW_BLUE_RIGHT_IMG, 
				[UNIT_ARROW_SPRITE_SHEET_CROP],
				1, true);
		
		return new AnimationBundle(
				animationHumanUpStand,
				animationHumanLeftStand,
				animationHumanRightStand,
				animationHumanDownStand,
				
				animationHumanUpWalk,
				animationHumanLeftWalk,
				animationHumanRightWalk,
				animationHumanDownWalk,
				
				animationBlueArrowLeft,
				animationBlueArrowRight
		);
		
	};
	
	this.createSkeletonAnimationBundle = function() {
		var animationSkeletonUpStand = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_0_0],
				1, true);

		var animationSkeletonUpWalk = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_0_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_0_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationSkeletonLeftStand = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_1_0],
				1, true);

		var animationSkeletonLeftWalk = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_1_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_1_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationSkeletonDownStand = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_2_0],
				1, true);

		var animationSkeletonDownWalk = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_2_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_2_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationSkeletonRightStand = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_3_0],
				1, true);

		var animationSkeletonRightWalk = new Animation(UNIT_SKELETON_SPRITE_SHEET_IMG, 
				[UNIT_HUMANOID_SPRITE_SHEET_CROP_3_1,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_2,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_3,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_4,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_5,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_6,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_7,
				 UNIT_HUMANOID_SPRITE_SHEET_CROP_3_8,
				 ],
				 ANIMATION_WALK_FPS, true);

		var animationRedArrowLeft = new Animation(ARROW_RED_LEFT_IMG, 
				[UNIT_ARROW_SPRITE_SHEET_CROP],
				1, true);

		var animationRedArrowRight = new Animation(ARROW_RED_RIGHT_IMG, 
				[UNIT_ARROW_SPRITE_SHEET_CROP],
				1, true);
		
		return new AnimationBundle(
				animationSkeletonUpStand,
				animationSkeletonLeftStand,
				animationSkeletonRightStand,
				animationSkeletonDownStand,
				
				animationSkeletonUpWalk,
				animationSkeletonLeftWalk,
				animationSkeletonRightWalk,
				animationSkeletonDownWalk,
				
				animationRedArrowLeft,
				animationRedArrowRight
		);
	};	

}
